package com.cc.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.cc.common.utils.R;
import com.cc.common.utils.ResponseData;
import com.cc.common.utils.ResultMsg;
import com.cc.user.entity.LoginUserEntity;
import com.cc.user.entity.RegistUserEntity;
import com.cc.user.entity.UserEntity;
import com.cc.user.feign.ThirdPartFeignService;
import com.cc.user.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@RequestMapping("user/login")
@Api(tags="登录注册")
public class LoginController {

    @Autowired
    private ThirdPartFeignService thirdPartFeignService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    /**
     * 发送验证码
     * @param phone
     * @return
     */
    @GetMapping("/sms/sendcode")
    @ApiOperation("根据手机号发送验证码")
    @ApiImplicitParam(name = "phone",value = "手机号码",paramType = "query",dataType = "String",required = true)
    public ResponseData sendCode(@RequestParam("phone") String phone){
        //接口防刷
        String redisCode = redisTemplate.opsForValue().get("sms:code:" + phone);
        if (!StringUtils.isEmpty(redisCode)) {
            //活动存入redis的时间，用当前时间减去存入redis的时间，判断用户手机号是否在60s内发送验证码
            long currentTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - currentTime < 60000) {
                //60s内不能再发
                return ResponseData.success("短信验证码频率太高，稍后再试！",false);
            }
        }
        //验证码的再次校验
        String code = UUID.randomUUID().toString().substring(0, 4);
        String code_redis = code +"_"+System.currentTimeMillis();
        //存入redis，防止同一个手机号在60秒内再次发送验证码
        redisTemplate.opsForValue().set("sms:code:"+phone, code_redis,1, TimeUnit.MINUTES);
        thirdPartFeignService.sendCode(phone,code);
        return ResponseData.success("发送成功",true);
    }

    /**
     * 用户注册
     * @param registUser
     * @param result
     * @return
     */
    @ApiOperation("用户注册")
    @PostMapping("/regist")
    public ResponseData regist(@Valid RegistUserEntity registUser, BindingResult result){
        //检查传入的数据是否有错
        if(result.hasErrors()){
            //校验出错，转发到注册页
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            String errorsString = JSONObject.toJSONString(errors);
            return ResponseData.success(errorsString,false);
        }
        //检查手机号是否已经注册
        if (userService.checkMobileUnique(registUser.getPhone(), registUser.getPermission())){
            //手机号已经注册
            return ResponseData.success("手机号已注册",false);
        }
        //开始注册
        //校验验证码
        String code = registUser.getCode();
        String codeRedisKey = "sms:code:" + registUser.getPhone();
        String s = redisTemplate.opsForValue().get(codeRedisKey);
        if (!StringUtils.isEmpty(s) && code.equals(s.split("_")[0])) {
            //删除验证码session
            redisTemplate.delete(codeRedisKey);
            //验证码通过，开始注册
            UserEntity user = new UserEntity();
            user.setMobile(registUser.getPhone());
            //密码加密进行存储
            String encode_password = new BCryptPasswordEncoder().encode(registUser.getPassword());
            user.setPassword(encode_password);
            user.setPermission(registUser.getPermission());
            //设置创建用户的时间和默认审核状态
            SimpleDateFormat sim=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            user.setCreatetime(sim.format(new Date()));
            user.setVerifyStatus(0);

            //给客户添加店铺名称、店铺地址、联系人姓名
            if(registUser.getPermission() == 2) {
                user.setShopName(registUser.getShopName());
                user.setContactName(registUser.getContactName());
                user.setShopAddress(registUser.getShopAddress());
            }
            userService.save(user);

            //注册成功回到登录页面
            return ResponseData.success("提交成功，请等待审核！",true);
        }else{
            //校验出错，转发到注册页面
            return ResponseData.success("验证码错误",false);
        }
    }

    @ApiOperation("通过密码登录")
    @PostMapping("/pwdLogin")
    public ResponseData pwdLogin(LoginUserEntity loginUser, HttpSession session){
        if (!userService.checkMobileUnique(loginUser.getPhone(), loginUser.getPermission())){
            //手机号没有注册
            return ResponseData.success("手机号未注册",false);
        }

        UserEntity userEntity = userService.pwdlogin(loginUser);
        if (userEntity == null){
            //登录失败
            return ResponseData.success("密码错误",false);
        }
        if(userEntity.getVerifyStatus() == 0){
            //审核未通过
            return ResponseData.success("审核未通过",false);
        }
        //登录成功
        session.setAttribute("loginuser",userEntity);

        redisTemplate.opsForValue().set("user:" + userEntity.getMobile(), session.getId(),2,TimeUnit.HOURS);
        return ResponseData.success("登录成功",true);
    }

    @ApiOperation("通过验证码登录")
    @PostMapping("/codeLogin")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号码", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "code", value = "验证码", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "permission",value = "用户类别,1：普通员工2：客户",paramType = "query",dataType = "int",required = true,allowableValues = "1,2")
    })
    public ResponseData codeLogin(@RequestParam("phone") String phone, @RequestParam("code") String code, @RequestParam("permission") Long permission, HttpSession session){
        String codeRedisKey = "sms:code:" + phone;
        String s = redisTemplate.opsForValue().get(codeRedisKey);
        if (!StringUtils.isEmpty(s) && code.equals(s.split("_")[0])) {
            //删除验证码session
            redisTemplate.delete(codeRedisKey);

            UserEntity userEntity = userService.loginByPhone(phone, permission);
            if (userEntity == null){
                //手机号未注册登录失败
                return ResponseData.success("手机号未注册",true);
            }
            if(userEntity.getVerifyStatus() == 0){
                //审核未通过
                return ResponseData.success("审核未通过",false);
            }
            //登录成功
            session.setAttribute("loginuser",userEntity);
            redisTemplate.opsForValue().set("user:" + userEntity.getMobile(), session.getId(),2,TimeUnit.HOURS);
            //注册成功回到主页面
            return ResponseData.success("登录成功",true);
        }else{
            //校验出错，转发到登录页面
            return ResponseData.success("验证码错误",false);
        }
    }

    @ApiOperation("用户密码更新")
    @PostMapping("/updatePwd")
    public ResponseData updatePwd(@Valid RegistUserEntity registUser, BindingResult result, HttpSession session){
        //检查传入的数据是否有错
        if(result.hasErrors()){
            //校验出错，转发到注册页
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            String errorsString = JSONObject.toJSONString(errors);
            return ResponseData.success(errorsString,false);
        }
        //检查手机号是否已经注册
        if (!userService.checkMobileUnique(registUser.getPhone(), registUser.getPermission())){
            //手机号未注册
            return ResponseData.success("手机号未注册",true);
        }
        //校验验证码
        String code = registUser.getCode();
        String codeRedisKey = "sms:code:" + registUser.getPhone();
        String s = redisTemplate.opsForValue().get(codeRedisKey);
        if (!StringUtils.isEmpty(s) && code.equals(s.split("_")[0])) {
            //验证码通过，开始更新密码
            //删除验证码session
            redisTemplate.delete(codeRedisKey);
            //密码加密
            UserEntity user = new UserEntity();
            String encode_password = new BCryptPasswordEncoder().encode(registUser.getPassword());
            user.setPassword(encode_password);
            int flag = userService.update(registUser.getPhone(),user);
            if (flag != 1) {
                return ResponseData.success("密码更改失败",false);
            }
            //更新session用户信息
            session.setAttribute("loginuser",user);
            //注册成功回到登录页面
            return ResponseData.success("密码已更改",true);
        }else{
            //校验出错，转发到注册页面
            return ResponseData.success("验证码错误",false);
        }
    }

    @ApiOperation("退出登录")
    @PostMapping("/outLogin")
    public ResponseData outLogin(HttpSession session){
        //session.removeAttribute("loginuser");
        //session.invalidate();
        UserEntity user = (UserEntity) session.getAttribute("loginuser");
        redisTemplate.delete("user:" + user.getMobile());

        session.setMaxInactiveInterval(-2);
        session.invalidate();
        //退出登录成功
        return ResponseData.success("退出登录成功",true);
    }
}
